package ${classPath};

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
import java.util.Set;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root; 
import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.Range;
import org.springframework.data.jpa.domain.Specification;
import top.lemna.base.core.dto.range.TimeRange;
import lombok.Data;
import lombok.ToString;
import lombok.experimental.Accessors;

@Data
@ToString
@Accessors(chain = true)
public class  ${domain}Query {

<#list fieldList as field>

<#compress>
  /** ${field.comment} */
<#list field.annotations as annotation> 
<#if !annotation?starts_with("@Column")&&!annotation?starts_with("@Not")>
  ${annotation}
</#if>
</#list>
  private ${field.type} ${field.name};
</#compress>

<#if field.name?ends_with("ype") || field.name?ends_with("tatus")>
  
  /** 排除${field.comment} */
  @Size(max = 5)
  private Set<${field.type}> exclude${field.name?cap_first};
 
  /** 包含${field.comment} */
  @Size(max = 5)
  private Set<${field.type}> include${field.name?cap_first};
</#if>
</#list>
  
  /** 创建时间 */
  private TimeRange createTime; 

  public Specification<${domain}> getSpecification()
  {
    return new Specification<${domain}>() {
      private static final long serialVersionUID = 1L;

      @Override
      public Predicate toPredicate(Root<${domain}> root, CriteriaQuery<?> query, CriteriaBuilder cb) {


    List<Predicate> predicate = new ArrayList<>();

  <#list fieldList as field>
      /** ${field.comment} */
      if (${field.name} != null) {
        predicate.add(cb.equal(root.get("${field.name}"), ${field.name}));
      }
      
  <#if field.name?ends_with("ype") || field.name?ends_with("tatus")>
      /** 包含${field.comment} */
      if (include${field.name?cap_first} != null && include${field.name?cap_first}.size() > 0) {
        Path<${field.type}> path = root.get("${field.name}");
        CriteriaBuilder.In<Object> in = cb.in(path);
        for (${field.type} ${field.name} : include${field.name?cap_first}) {
          in.value(${field.name});
        }
        predicate.add(in);
      }
  
      /** 排除${field.comment} */
      if (exclude${field.name?cap_first} != null && exclude${field.name?cap_first}.size() > 0) {
        Path<${field.type}> path = root.get("${field.name}");
        CriteriaBuilder.In<Object> in = cb.in(path);
        for (${field.type} ${field.name} : exclude${field.name?cap_first}) {
          in.value(${field.name});
        }
        predicate.add(cb.not(in));
      }
      
  </#if>
  </#list>
      if (createTime != null && createTime.getStart() != null) {
        predicate.add(cb.greaterThanOrEqualTo(root.get("createTime"), createTime.getStart()));
      }
      if (createTime != null && createTime.getEnd() != null) {
        predicate.add(cb.lessThanOrEqualTo(root.get("createTime"), createTime.getEnd()));
      }
      
      Predicate[] pre = new Predicate[predicate.size()];
      return query.where(predicate.toArray(pre)).getRestriction();
      }
    };
  }
}